package com.trace.demo.controller;

import com.trace.demo.dto.LoginRequest;
import com.trace.demo.dto.RegisterRequest;
import com.trace.demo.entity.LoginLog;
import com.trace.demo.entity.User;
import com.trace.demo.repository.LoginLogRepository;
import com.trace.demo.repository.UserRepository;
import com.trace.demo.response.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/api/users")
public class AuthController {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final LoginLogRepository loginLogRepository;

    // 用户名验证模式：只允许字母或数字，长度不少于六位
    private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]{6,}$");
    // 密码验证模式：至少包含一个字母和一个数字，长度不少于8位
    private static final Pattern PASSWORD_PATTERN = Pattern.compile("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{6,}$");

    @Autowired
    public AuthController(UserRepository userRepository, PasswordEncoder passwordEncoder, LoginLogRepository loginLogRepository) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
        this.loginLogRepository = loginLogRepository;
    }

    @PostMapping("/register")
    public ResponseEntity<ApiResponse<User>> register(@RequestBody RegisterRequest registerRequest) {
        // 检查用户名格式是否符合规范
        System.out.println("接受到的数据"+ registerRequest);
        String username = registerRequest.getUsername();
//        if (username == null || !USERNAME_PATTERN.matcher(username).matches()) {
//            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
//                    .body(new ApiResponse<>(false, "用户名必须由字母或数字组成，长度不少于六位", null));
//        }

        // 检查密码格式是否符合规范
        String password = registerRequest.getPassword();
        if (password == null || !PASSWORD_PATTERN.matcher(password).matches()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(new ApiResponse<>(false, "密码必须至少包含一个字母和一个数字，长度不少于6位", null));
        }

        // 检查用户名是否已存在
        if (userRepository.existsByUsername(username)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(new ApiResponse<>(false, "用户名已存在", null));
        }

        // 验证邮箱(如果提供了)
        String email = registerRequest.getEmail();
        if (email != null && !email.isEmpty() && !isValidEmail(email)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(new ApiResponse<>(false, "邮箱格式不正确", null));
        }

        // 创建新用户
        User user = new User();
        user.setUsername(registerRequest.getUsername());
        // 加密密码
        user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
        user.setRole(registerRequest.getRole());
        user.setEmail(registerRequest.getEmail());
        user.setPhone(registerRequest.getPhone());
        user.setCreatedAt(LocalDateTime.now());
        user.setStatus(1); // 默认状态为启用

        User savedUser = userRepository.save(user);

        // 出于安全考虑，返回用户信息时不包含密码
        savedUser.setPassword(null);

        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new ApiResponse<>(true, "用户注册成功", savedUser));
    }

    @PostMapping("/login")
    public ResponseEntity<ApiResponse<Map<String, Object>>> login(@RequestBody LoginRequest loginRequest, HttpServletRequest request) {
        // 记录登录日志所需的信息
        String ipAddress = getIpAddress(request);
        String userAgent = request.getHeader("User-Agent");
        String browser = getBrowserInfo(userAgent);
        String os = getOsInfo(userAgent);
        String location = "Unknown"; // 实际应用中可以通过IP地址获取地理位置
        
        // 根据用户名查找用户
        Optional<User> userOptional = userRepository.findByUsername(loginRequest.getUsername());
        
        // 创建登录日志对象
        LoginLog loginLog = new LoginLog();
        loginLog.setUserName(loginRequest.getUsername());
        loginLog.setIpAddress(ipAddress);
        loginLog.setBrowser(browser);
        loginLog.setOs(os);
        loginLog.setLocation(location);
        loginLog.setLoginTime(LocalDateTime.now());
        loginLog.setCreatedAt(LocalDateTime.now());

        if (!userOptional.isPresent()) {
            // 记录登录失败日志
            loginLog.setStatus("failure");
            loginLog.setMessage("用户名不存在");
            loginLogRepository.save(loginLog);
            
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ApiResponse<>(false, "用户名或密码错误", null));
        }

        User user = userOptional.get();
        
        // 检查用户状态
        if (user.getStatus() != 1) {
            // 记录登录失败日志
            loginLog.setStatus("failure");
            loginLog.setMessage("账户已被禁用");
            loginLog.setUserId(user.getId());
            loginLogRepository.save(loginLog);
            
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(new ApiResponse<>(false, "账户已被禁用，请联系管理员", null));
        }

        boolean passwordMatches = false;
        
        // 检查密码是否以BCrypt格式开头
        if (user.getPassword().startsWith("$2a$")) {
            // 使用BCrypt验证密码
            passwordMatches = passwordEncoder.matches(loginRequest.getPassword(), user.getPassword());
        } else {
            // 如果不是BCrypt格式，直接比较密码（不安全，仅作过渡）
            passwordMatches = loginRequest.getPassword().equals(user.getPassword());
            
            // 可选：登录成功后将密码更新为BCrypt格式
            if (passwordMatches) {
                user.setPassword(passwordEncoder.encode(loginRequest.getPassword()));
                userRepository.save(user);
            }
        }
        
        if (!passwordMatches) {
            // 记录登录失败日志
            loginLog.setStatus("failure");
            loginLog.setMessage("密码错误");
            loginLog.setUserId(user.getId());
            loginLogRepository.save(loginLog);
            
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ApiResponse<>(false, "用户名或密码错误", null));
        }

        // 记录登录成功日志
        loginLog.setStatus("success");
        loginLog.setMessage("登录成功");
        loginLog.setUserId(user.getId());
        loginLogRepository.save(loginLog);
        
        // 创建响应数据
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("id", user.getId());
        responseData.put("username", user.getUsername());
        // 确保角色字段与前端期望的一致
        responseData.put("role", user.getRole().toString()); // 转为字符串确保与前端期望格式一致
        responseData.put("email", user.getEmail());
        responseData.put("phone", user.getPhone());
        responseData.put("token", "mock-jwt-token-" + user.getId()); // 实际项目中应该生成真实的JWT令牌
        responseData.put("avatar", user.getAvatar());
        responseData.put("status", user.getStatus());

        // 确保返回200 OK状态码，成功标志为true
        return ResponseEntity.ok(new ApiResponse<>(true, "登录成功", responseData));
    }

    @GetMapping("/current")
    public ResponseEntity<ApiResponse<User>> getCurrentUser(@RequestHeader("Authorization") String token) {
        // 从token中提取用户ID（实际项目中应该解析JWT令牌）
        String tokenPrefix = "Bearer mock-jwt-token-";
        if (!token.startsWith(tokenPrefix)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ApiResponse<>(false, "无效的令牌", null));
        }

        try {
            Long userId = Long.parseLong(token.substring(tokenPrefix.length()));
            Optional<User> userOptional = userRepository.findById(userId);

            if (!userOptional.isPresent()) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND)
                        .body(new ApiResponse<>(false, "用户不存在", null));
            }

            User user = userOptional.get();
            user.setPassword(null); // 不返回密码

            return ResponseEntity.ok(new ApiResponse<>(true, "获取用户信息成功", user));
        } catch (NumberFormatException e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ApiResponse<>(false, "无效的令牌", null));
        }
    }

    @GetMapping("/auth/{id}")
    public ResponseEntity<ApiResponse<User>> getUserById(@PathVariable Long id) {
        Optional<User> userOptional = userRepository.findById(id);

        if (!userOptional.isPresent()) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body(new ApiResponse<>(false, "用户不存在", null));
        }

        User user = userOptional.get();
        user.setPassword(null); // 不返回密码

        return ResponseEntity.ok(new ApiResponse<>(true, "获取用户信息成功", user));
    }

    @PutMapping("/update")
    public ResponseEntity<ApiResponse<User>> updateUser(@RequestBody User user, @RequestHeader("Authorization") String token) {
        // 从token中提取用户ID（实际项目中应该解析JWT令牌）
        String tokenPrefix = "Bearer mock-jwt-token-";
        if (!token.startsWith(tokenPrefix)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ApiResponse<>(false, "无效的令牌", null));
        }

        try {
            Long tokenUserId = Long.parseLong(token.substring(tokenPrefix.length()));

            // 验证token中的用户ID与要更新的用户ID是否一致
            if (!tokenUserId.equals(user.getId())) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                        .body(new ApiResponse<>(false, "您只能更新自己的个人资料", null));
            }

            Optional<User> existingUserOptional = userRepository.findById(user.getId());

            if (!existingUserOptional.isPresent()) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND)
                        .body(new ApiResponse<>(false, "用户不存在", null));
            }

            User existingUser = existingUserOptional.get();

            // 更新用户信息
            existingUser.setEmail(user.getEmail());
            existingUser.setPhone(user.getPhone());
            // 如果密码不为空，则更新密码
            if (user.getPassword() != null && !user.getPassword().isEmpty()) {
                existingUser.setPassword(user.getPassword()); // 实际项目中应该对密码进行加密处理
            }

            User updatedUser = userRepository.save(existingUser);
            updatedUser.setPassword(null); // 不返回密码

            return ResponseEntity.ok(new ApiResponse<>(true, "用户信息更新成功", updatedUser));
        } catch (NumberFormatException e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ApiResponse<>(false, "无效的令牌", null));
        }
    }

    @PutMapping("/password")
    public ResponseEntity<ApiResponse<Void>> changePassword(
            @RequestHeader("Authorization") String token,
            @RequestBody Map<String, String> passwordData) {
        
        // 从token中提取用户ID
        String tokenPrefix = "Bearer mock-jwt-token-";
        if (!token.startsWith(tokenPrefix)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ApiResponse<>(false, "无效的令牌", null));
        }
        
        try {
            Long userId = Long.parseLong(token.substring(tokenPrefix.length()));
            Optional<User> userOptional = userRepository.findById(userId);
            
            if (!userOptional.isPresent()) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND)
                        .body(new ApiResponse<>(false, "用户不存在", null));
            }
            
            User user = userOptional.get();
            
            // 验证旧密码
            String oldPassword = passwordData.get("oldPassword");
            if (oldPassword == null || !passwordEncoder.matches(oldPassword, user.getPassword())) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                        .body(new ApiResponse<>(false, "旧密码不正确", null));
            }
            
            // 验证新密码格式
            String newPassword = passwordData.get("newPassword");
            if (newPassword == null || !PASSWORD_PATTERN.matcher(newPassword).matches()) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                        .body(new ApiResponse<>(false, "新密码必须至少包含一个字母和一个数字，长度不少于8位", null));
            }
            
            // 更新密码
            user.setPassword(passwordEncoder.encode(newPassword));
            userRepository.save(user);
            
            return ResponseEntity.ok(new ApiResponse<>(true, "密码修改成功", null));
        } catch (NumberFormatException e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ApiResponse<>(false, "无效的令牌", null));
        }
    }
    
    // 辅助方法：验证邮箱格式
    private boolean isValidEmail(String email) {
        String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
        return Pattern.compile(emailRegex).matcher(email).matches();
    }

    /**
     * 获取客户端IP地址
     */
    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
    
    /**
     * 获取浏览器信息
     */
    private String getBrowserInfo(String userAgent) {
        if (userAgent == null) {
            return "Unknown";
        }
        userAgent = userAgent.toLowerCase();
        
        if (userAgent.contains("edge")) {
            return "Edge";
        } else if (userAgent.contains("firefox")) {
            return "Firefox";
        } else if (userAgent.contains("chrome")) {
            return "Chrome";
        } else if (userAgent.contains("safari") && !userAgent.contains("chrome")) {
            return "Safari";
        } else if (userAgent.contains("opera") || userAgent.contains("opr")) {
            return "Opera";
        } else if (userAgent.contains("msie") || userAgent.contains("trident")) {
            return "Internet Explorer";
        } else {
            return "Unknown";
        }
    }
    
    /**
     * 获取操作系统信息
     */
    private String getOsInfo(String userAgent) {
        if (userAgent == null) {
            return "Unknown";
        }
        userAgent = userAgent.toLowerCase();
        
        if (userAgent.contains("windows")) {
            return "Windows";
        } else if (userAgent.contains("mac")) {
            return "MacOS";
        } else if (userAgent.contains("linux")) {
            return "Linux";
        } else if (userAgent.contains("android")) {
            return "Android";
        } else if (userAgent.contains("iphone") || userAgent.contains("ipad")) {
            return "iOS";
        } else {
            return "Unknown";
        }
    }
}
